<?php
/******************************************************************************
 *
 *    OpenZoowa - Web App to manage events
 *    Copyright (C) 2008 Jesus Ruiz-Ayucar
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as
 *    published by the Free Software Foundation, either version 3 of the
 *    License, or (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *****************************************************************************/

/**
 * Clase para representar los usuarios
 *
 * Toda la lógica del usuario reside en esta clase. Desde crear uno nuevo, 
 * a validar o recuperar una cuenta
 * @author Jesus Ruiz-Ayucar  <chuso@zoowa.net>
 * @version 0.1
 * @package zoowalite
 */

   class User {
      private $id;
      private $login;
      private $authenticated;
      private $password;
      private $level;
      private $email;
      private $register_date;
      private $avatar;

      const min_login = 4;
      const max_login = 32;

      public function User($id = null) {
         global $db;
         if(isset($id)) {
            $SQL  = 'SELECT * FROM '.$GLOBALS["db_pre"].'users WHERE ';
            $SQL .= 'id = ' . $db->escape($id);
            $user = $db->get_row($SQL);
            if (isset($user)) {
               $this->id = $user->id;
               $this->login = $user->login;
               $this->authenticated = false;
               $this->password = null;
               $this->level = $user->level;
               $this->email = $user->email;
               $this->register_date = $user->register_date;
               $this->avatar = $user->avatar;
            }
         }
      }

      public function setUser() {
         global $db;

         if(!empty($_COOKIE[$GLOBALS['cookie_name']])) {
            $cookie = $_COOKIE[$GLOBALS['cookie_name']];
            $userInfo=explode(":", base64_decode($cookie));

            // En el tercer campo tenemos el timestamp
            $cookietime = (int) $userInfo[2];

            // Sanitize user login
            $dbusername = $db->escape($userInfo[0]);

            // Getting all needed info from the user
            $SQL  = 'SELECT * FROM '.$GLOBALS["db_pre"].'users WHERE ';
            $SQL .='login = "'.$db->escape($userInfo[0]).'"';
            $dbuser=$db->get_row($SQL);

            // after 10 days expiration is forced
            if (($GLOBALS['now'] - $cookietime) > 864000) {
               $cookietime = 'expired';
            }

            // And finally we make the md5 checksum for control
            $key = md5($dbuser->email.$dbusername.$dbuser->id.$cookietime);

            // Everything allright?
            if ( !$dbuser || !$dbuser->id > 0 || $dbuser->level == 'disabled'
               || $key !== $userInfo[1]  || empty($dbuser->register_date)) {
               $this->Logout('/');
               return;
            }

            // Upgrading attributes
            $this->id = $dbuser->id;
            $this->login  = $userInfo[0];
            $this->password = $dbuser->password;
            $this->level = $dbuser->level;
            $this->email = $dbuser->email;
            $this->register_date = $dbuser->register_date;
            $this->avatar = $dbuser->avatar;
            $this->authenticated = TRUE;

            // Update time each hour
            if ($GLOBALS['now'] - $cookietime > 3600) {
               $this->SetIDCookie(1, $userInfo[3] > 0 ? true : false);
            }
         }
      }

      function SetIDCookie($what, $persistent) {
         switch ($what) {
            // logout
            case 0:
               // Expire cookies
               setcookie ($GLOBALS['cookie_name'],
                  "",
                  $GLOBALS['now'] - 3600,
                  $GLOBALS['base_url'],
                  $GLOBALS['domain'],
                  0,
                  1);
               break;
            // User loged, updating cookie
            case 1:
               if($persistent) {
                  // Valid for 1000 hours
                  $time = $GLOBALS['now'] + 3600000;
               } else {
                  $time = 0;
               }

               $strCookie=base64_encode(
                  $this->login.':'
                  .md5($this->email.$this->login.$this->id.$GLOBALS['now']).':'
                  .$GLOBALS['now'].':'
                  .$time);

               setcookie($GLOBALS['cookie_name'],
                  $strCookie,
                  $time,
                  $GLOBALS['base_url'],
                  $GLOBALS['domain'],
                  0,
                  1);
               break;
         }
      }

      public function authenticate($login, $password, $persistent = true) {
         global $db;

         $SQL  = 'SELECT id, login, email, password, level, ';
         $SQL .= 'register_date FROM '.$GLOBALS["db_pre"].'users WHERE ';
         $SQL .= 'login = "'.$db->escape($login).'"';

         $user=$db->get_row($SQL);
         if ($user->level == 'disabled' || empty($user->register_date)) {
            return false;
         }
         if ($user->id > 0 && $user->password == md5($password)) {
            $this->login = $login;
            $this->id = $user->id;
            $this->authenticated = TRUE;
            $this->password = $user->password;
            $this->level = $user->level;
            $this->email = $user->email;

            // Finalmente creamos la cookie
            $this->SetIDCookie(1, $persistent);
            return true;
         }
         return false;
      }

      function logout($url='./') {
         $this->user_id = 0;
         $this->user_login = "";
         $this->authenticated = FALSE;
         $this->SetIDCookie (0, false);

         //header("Pragma: no-cache");
         header("Cache-Control: no-cache, must-revalidate");
         header("Location: $url");
         header("Expires: " . gmdate("r", $tGLOBALS['now'] - 3600));
         header('ETag: "logingout' . $GLOBALS['now'] . '"');
         die;
      }

      function sendActivation() {
         global $lang;
         $key = $this->id.$this->password.$GLOBALS['now'].Util::getServerName();
         $key = md5($key);

         $url  = Util::getServerName().$GLOBALS['base_url'];
         $url .= 'index.php?c=user&a=activate&login='.$this->login;
         $url .= '&n='.$GLOBALS['now'].'&k='.$key;

         $to = $this->email;

         $subject = $lang['activate_mail_subject'] . Util::getServerName();

         $tags = array('%USER%', '%URL%', '%IP%', '%HOST%');
         $values = array(
            $this->login,
            $url,
            $_SERVER['REMOTE_ADDR'],
            Util::getServerName()
         );
         $message = str_replace($tags, $values, $lang['activate_mail_text']);
         $message = wordwrap($message, 70);

         $headers  = 'Content-Type: text/plain; charset="utf-8"' . "\n";
         $headers .= 'From: '.Util::getServerName();
         $headers .= '<noreply@'.Util::getServerName() . ">\n";

         mail($to, $subject, $message, $headers);
      }

      function activate($login=null, $date=null, $key=null) {
         global $db;

         if ($GLOBALS['check_mail']) {
            $user = $db->get_row("SELECT * FROM users WHERE login = '$login'");

            // Comprobamos la clave
            $key2 = md5($user->id.$user->password.$date.Util::get_server_name());

            // Lo activamos sólo si se registró hace menos de dos horas.
            // y las claves coinciden
            if ($date > $GLOBALS['now'] - 7200 &&
                  $date < $GLOBALS['now'] &&
                  $key == $key2) {
               $SQL  = 'UPDATE '.$GLOBALS["db_pre"].'users ';
               $SQL .= 'SET level = "standard", ';
               $SQL .= 'register_date = now() WHERE id = '.$user->id;
               return $db->query($SQL);
            } else {
               return false;
            }
         } else {
            $SQL  = 'UPDATE '.$GLOBALS["db_pre"].'users ';
            $SQL .= 'SET level = "standard", ';
            $SQL .= 'register_date = now() WHERE id = '.$this->id;
            return $db->query($SQL);
         }
      }

      function add() {
         global $db;
         // Si había un usuario con el mismo login o correo pero que no
         // registró su cuenta, lo borramos
         $SQL  = 'DELETE FROM '.$GLOBALS["db_pre"].'users WHERE ';
         $SQL .= 'level="disabled" AND ';
         $SQL .= '(login="'.$this->login.'" OR email="'.$this->email.'")';
         $db->query($SQL);

         $SQL  = 'INSERT INTO '.$GLOBALS["db_pre"].'users ';
         $SQL .= '(login, email, password) VALUES (';
         $SQL .= '"'.$db->escape($this->login).'",';
         $SQL .= '"'.$db->escape($this->email).'",';
         $SQL .= '"'.$this->password.'")';

         if ($db->query($SQL)) {
            $this->id = $db->insert_id;
            $this->sendActivation();
            return $this->id;
         }
      }

      function sendRecover($email) {
         global $db, $lang;

         $SQL = 'SELECT * FROM '.$GLOBALS["db_pre"].'users WHERE ';
         $SQL .= 'email = "'.$db->escape($email).'" AND level != "disabled"';
         $user = $db->get_row($SQL);

         if (isset($user) && strlen($email) < 256) {
            $key  = $user->id.$user->password.$GLOBALS['now'];
            $key .= Util::getServerName();
            $key = md5($key);

            $url  = 'http://'.Util::getServerName().$GLOBALS['base_url'];
            $url .= 'index.php?c=user&a=recover&login='.$user->login;
            $url .= '&n='.$GLOBALS['now'].'&k='.$key;

            $to = $user->email;

            $subject = $lang['recover_mail_subject']. Util::getServerName();

            $tags = array('%USER%', '%URL%', '%IP%', '%HOST%');
            $values = array(
               $user->login,
               $url,
               $_SERVER['REMOTE_ADDR'], Util::getServerName());

            $message = str_replace($tags, $values, $lang['recover_mail_text']);
            $message = wordwrap($message, 70);
            $headers = 'Content-Type: text/plain; charset="utf-8"'."\n";
            $headers .= 'From: '.Util::getServerName();
            $headers .= '<noreply@'.Util::getServerName().">\n";
            echo "#".$to."<br />#".$subject."<br />#".$message."<br />#".$headers;
            //mail($to, $subject, $message, $headers);

            return true;
         } else {
            return false;
         }
      }

      function recover($login, $date, $key) {
         global $db;

         $user = $db->get_row("SELECT * FROM users WHERE login = '$login'");

         $key2 = md5($user->id.$user->password.$date.Util::getServerName());
         if ($date > $GLOBALS['now'] - 7200 &&
               $date < $GLOBALS['now'] &&
               $key == $key2) {
            // La url es correcta. Le autenticamos
            $this->login = $login;
            $this->id = $user->id;
            $this->authenticated = TRUE;
            $this->password = $user->password;
            $this->level = $user->level;
            $this->email = $user->email;
            $this->SetIDCookie(1, false);
            return true;
         } else {
                  return false;
         }
      }

      function update() {
         global $db;

         $SQL  = 'UPDATE '.$GLOBALS["db_pre"].'users SET ';
         $SQL .= 'password = "' . $this->password . '", ';
         $SQL .= 'email = "' . $db->escape($this->email) . '", ';
         $SQL .= 'avatar = ' . $this->avatar . " ";
         $SQL .= 'WHERE id = ' . $this->id;
         $db->query($SQL);

         return true;
      }

      public function getLastInserted() {
         global $db;

         $SQL  = 'SELECT id ';
         $SQL .= 'FROM '.$GLOBALS["db_pre"].'events ';
         $SQL .= 'WHERE user_id = ' . $this->id . ' ';
         $SQL .= 'ORDER BY date_post desc ';
         $SQL .= 'LIMIT 0,5';

         $resul = $db->get_col($SQL);
         for($i = 0; $i< count($resul); $i++) {
            $events[$i] = new Event($resul[$i]);
         }
         return $events;
      }

      public function setEmail($email) {
         global $lang, $db;

         $SQL  = 'SELECT count(*) FROM '.$GLOBALS["db_pre"].'users WHERE ';
         $SQL .= 'email = "'.$db->escape($email).'" AND ';
         $SQL .= 'level != "disabled"';

         if(isset($this->id)) {
            $SQL .= 'AND id != ' . $this->id;
         }
         $pattern = '^[a-zA-Z0-9._-]+@[\.a-zA-Z0-9-]+\.[a-zA-Z.]{2,5}$';
         $cond1 = eregi($pattern, $email);
         $cond2 = strlen($email) < 256;

         if ($db->get_var($SQL)) {
            return $lang['register_err_mail_used'];
         } elseif (!$cond1) {
            return $lang['register_err_mail'];
         } elseif (!$cond2) {
            return $lang['register_err_mail2'];
         } else {
            $this->email = $email;
            return null;
         }
      }

      public function setLogin($login) {
         global $db;
         global $lang;

         // Si el usuario está activo, impera la ley del más rápido
         $SQL  = 'SELECT count(*) FROM '.$GLOBALS["db_pre"].'users WHERE ';
         $SQL .= 'login = "'.$db->escape($login).'" AND level != "disabled"';
         $cond = eregi('^[a-zA-Z0-9_-]{'.self::min_login.','.self::max_login.'}$', $login);

         if ($db->get_var($SQL)) {
            return $lang['register_err_name_used'];
         } elseif (!$cond) {
            return $lang['register_err_forbiden_name'];
         } else {
            $this->login = $login;
            return null;
         }
      }

      public function setPassword($pass1, $pass2) {
         global $lang;

         if (empty($pass1)) {
            return $lang['register_err_empty_pass'];
         } elseif($pass1 != $pass2) {
            return $lang['user_err_pass'];
         } else {
            $this->password = md5($pass1);
         }
      }

      public function setAvatar($avatar) {
         global $lang;

         $avatar_path = avatarpath . $this->id . ".jpg";
         if(isset($avatar)) {
            $uploadfiletmp = avatarpath . $this->id . ".tmp";
            if (move_uploaded_file($avatar['tmp_name'], $uploadfiletmp)) {
               if(eregi('^.+\.jpe?g$', $avatar['name'])) {
                  $source = imagecreatefromjpeg($uploadfiletmp);
               } elseif(eregi('^.+\.png$', $avatar['name'])) {
                  $source = imagecreatefrompng($uploadfiletmp);
               } elseif(eregi('^.+\.gif$', $avatar['name'])) {
                  $source = imagecreatefromgif($uploadfiletmp);
               } else {
                  return $lang['invalid_image_err'];
               }

               $width = imagesx($source);
               $height = imagesy($source);

               $thumb = imagecreatetruecolor(80, 80);
               imagecopyresampled(
                  $thumb,
                  $source,
                  0,
                  0,
                  0,
                  0,
                  80,
                  80,
                  $width,
                  $height);
               imagejpeg($thumb, $avatar_path, 100);


               unlink($uploadfiletmp);
               $this->avatar = $this->id;
               return null;
            } else {
               return $lang['invalid_image_err'];
            }
         } else {
            $this->avatar = 0;
            unlink($avatar_path);
            return null;
         }
      }

      public function getId() {
         return $this->id;
      }

      public function getLogin() {
         return $this->login;
      }

      public function getAuthenticated() {
         return $this->authenticated;
      }

      public function getPassword() {
         return $this->password;
      }

      public function getLevel() {
         return $this->level;
      }

      public function getemail() {
         return $this->email;
      }

      public function getRegisterDate() {
         return $this->register_date;
      }

      public function getAvatar() {
         return $this->avatar;
      }

      public function __toString() {
         return $this->login;
      }

      public static function getIdFromLogin($login) {
         global $db;

         $SQL  = 'SELECT id FROM '.$GLOBALS["db_pre"].'users WHERE ';
         $SQL .= 'login = "' . $db->escape($login) . '"';
         return $db->get_var($SQL);
      }
   }
?>